﻿using System;
using System.ComponentModel;
using System.Drawing;
using ArtMath.Resource;
using System.Diagnostics;
using ArtMath.Component.Line;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Helper;
using ArtMath.Setting;

namespace ArtMath.Component.Polygon
{
    /// <summary>
    /// 任意多边形
    /// </summary>
    [Serializable]
    public class ArbitraryPolygon : PolygonBase
    {
        static Stopwatch sw = new Stopwatch();
        static bool checkInterval = true;
        public ArbitraryPolygon(SketchPad pad, string name, bool addToList = true) : base(pad, name, ToolTypeName.rydbx, addToList)
        {
        }
        public override bool PointsHaveConstraint
        {
            get { return false; }
        }
        [Browsable(false)]
        public bool IsRegularPolygon
        {
            get
            {
                for (int i = 1; i < Lines.Count; i++)
                {
                    if (!Lines[i].Length.AlmostEqual(Lines[0].Length))
                    {
                        return false;
                    }
                }
                return true;
            }
        }
        void AddLine(LineSegmentBase value)
        {
            Lines.Add(value);
            value?.InHosts.Add(this);
        }
        public override void ComponentBuilding(Base component)
        {
            if (Lines.Count == 0 || Lines[0].Point1 == null) return;
            Circumference = Area = 0;
            PointD pt = Pad.PxyToXY(Lines[Lines.Count - 1].SpareCoordinate);
            PointD[] node = new PointD[Lines.Count + 1];
            for (int i = 0; i < Lines.Count; i++)
            {
                Circumference += Lines[i].Length;
                node[i] = Lines[i].Point1.ToPointD();
                PointD tmp = i == Lines.Count - 1 ? pt : Lines[i + 1].Point1.ToPointD();
                Area += node[i].X * tmp.Y - node[i].Y * tmp.X;
            }
            node[node.Length - 1] = pt;
            Circumference += pt.DistanceTo(Lines[0].Point1.ToPointD());
            Area += pt.X * Lines[0].Point1.Y.Value - pt.Y * Lines[0].Point1.X.Value;
            Area = Math.Abs(Area) / 2;
            BaryCenter = Utility.GetBaryCenter(node);
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}{Resources.LeftParenthesis}{Resources.Translate("EndCreationImmediately")}");
            base.ComponentBuilding(component);
        }
        public override void PaintVirtualObjects(Graphics gra)
        {
            PointF[] pts = new PointF[Lines.Count + 1];
            for (int i = 0; i < Lines.Count; i++)
            {
                pts[i] = Lines[i].Point1.Pxy.ToPointF();
                if (Pad.TrackObj == Lines[i])
                {
                    pts[i + 1] = Lines[i].SpareCoordinate_.ToPointF();
                    gra.FillPolygon(Core.Helper.Painter.VirtualBrush, pts);
                    gra.DrawLineSegment(Lines[i].SpareCoordinate_, Lines[0].Point1.Pxy);
                    break;
                }
            }
        }
        public override void CreateComponents()
        {
            LineSegmentBase line;
            if (Lines.Count == 0)
            {
                line = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Edge")}1", false) { SpareCoordinate_ = SpareCoordinate_, };
                AddLine(line);
                line.CreateComponents($"{Resources.Translate("Edge")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Edge")}");
            }
            else
            {
                if (sw.IsRunning)
                {
                    sw.Stop();
                    if (checkInterval && sw.ElapsedMilliseconds <= Utility.GetDblClickInterval()) return;//双击前会触发单击事件，双击表示创建结束，则不再新建一线段
                    sw.Reset();
                }
                line = Pad.TrackObj as LineSegmentBase;
                line.CreateComponents($"{Resources.Translate("Edge")}{Lines.Count + 1}{Resources.Join}{Resources.Translate("EndPoint")}1/{line.Name}{Resources.Join}{Resources.Translate("EndPoint")}2");
                if (line.Point2.PDistanceTo(Lines[0].Point1) <= Settings.Instance.PointAbsorb)
                {
                    Complete();
                }
                else
                {
                    AddLine(new TwoPointsLineSegment(Pad, $"{Resources.Translate("Edge")}{Lines.Count + 1}", false));
                    Lines[Lines.Count - 1].CreateComponents(line.Point2);
                    sw.Start();
                }
            }
        }
        /// <summary>
        /// 完成任意多边形的创建
        /// </summary>
        /// <param name="line"></param>
        public void Complete()
        {
            LineSegmentBase line = Lines[Lines.Count - 1];
            if (line.Point2 != Lines[0].Point1)
            {
                line.CreateComponents(Lines[0].Point1, true);
                Lines[0].Point1.Name += $"{Lines.Count}{Resources.Join}{Resources.Translate("EndPoint")}2";
            }
            Name = Utility.GetNextAvailableName($"{Resources.Translate("Arbitrary")}{Resources.Join}{string.Format(Resources.Translate("NSided"), Lines.Count)}" + (Pad.CountToolType(ToolType) + 1), Pad.CheckObjectNameExist);
            base.CreateComponents();
        }
        public override void AutoCreate(object createInfo, bool tryOffset = false)
        {
            checkInterval = false;
            base.AutoCreate(createInfo, tryOffset);
            checkInterval = true;
        }
    }
}
